/// `Pipeline.process()` 的返回类型, 用以判断 item 是否进入下一个 pipeline 处理
pub enum ItemProduct<ItemType> {
    /// 进入下个 pipeline 处理
    Item(ItemType),
    /// 不进入下个 pipeline
    Ignore,
}

pub trait Pipeline<ItemType>: Send {
    fn open_spider(&mut self) {}
    /// 处理 item
    fn process(&mut self, item: ItemType) -> ItemProduct<ItemType>;
    fn close_spider(&mut self) {}
}

pub struct ConsolePipeline;

impl<ItemType: std::fmt::Debug> Pipeline<ItemType> for ConsolePipeline {
    fn process(&mut self, item: ItemType) -> ItemProduct<ItemType> {
        println!("{:?}", item);
        ItemProduct::Item(item)
    }
}

use csv;
use serde::Serialize;
pub struct CsvPipeline {
    wtr: csv::Writer<std::fs::File>,
}

impl CsvPipeline {
    pub fn new(path: &str) -> Self {
        Self {
            wtr: csv::Writer::from_path(path).unwrap(),
        }
    }
}

impl<ItemType: Serialize + std::fmt::Debug> Pipeline<ItemType> for CsvPipeline {
    fn open_spider(&mut self) {
        // self.wtr = csv::Writer::from_path("data/output.csv").unwrap();
    }
    fn process(&mut self, item: ItemType) -> ItemProduct<ItemType> {
        self.wtr.serialize(item).unwrap_or_else(|item| {
            println!("{:?} 写入失败", item);
            ()
        });
        ItemProduct::Ignore
    }
    fn close_spider(&mut self) {}
}
